package org.amos.server.modules.quartz.utils;

import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.amos.core.basic.constant.SystemConstant;
import org.amos.core.basic.exception.ServiceException;
import org.amos.server.modules.quartz.entity.QuartzJob;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Objects;

@Slf4j
@Component
public class QuartzUtil {


    public static final String DEFAULT_GROUP = "DEFAULT";

    @Autowired
    private Scheduler scheduler;

    public void add(QuartzJob quartzJob) {
        try {
            //构建job信息
            String jobClassName = quartzJob.getClassName();
            String params = quartzJob.getParams();
            String cronExpression = quartzJob.getCronExpression();
            JobDetail jobDetail = JobBuilder.newJob(getClass(jobClassName).getClass())
                    .withIdentity(quartzJob.getJobName(), quartzJob.getJobGroupName())
                    .usingJobData(SystemConstant.QUARTZ_JOB_PARAMS_NAME, params)
                    .build();
            try {
                JobKey jobKey = JobKey.jobKey(quartzJob.getJobName(), quartzJob.getJobGroupName());
                JobDetail detail = scheduler.getJobDetail(jobKey);
                if (Objects.nonNull(detail)) {
                    scheduler.deleteJob(jobKey);
                }
            } catch (SchedulerException e) {
                log.error("删除定时任务失败", e);
            }

            //表达式调度构建器(即任务执行的时间) 使用withMisfireHandlingInstructionDoNothing() 忽略掉调度暂停过程中没有执行的调度
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression).withMisfireHandlingInstructionDoNothing();

            //按新的cronExpression表达式构建一个新的trigger
            CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(jobClassName)
                    .withSchedule(scheduleBuilder).build();

            scheduler.scheduleJob(jobDetail, trigger);
        } catch (SchedulerException e) {
            log.error(e.toString());
        } catch (Exception e) {
            log.error("创建定时任务失败", e);
            throw new ServiceException("创建定时任务失败");
        }
    }

    /**
     * 暂停任务
     *
     * @param jobName
     * @param jobGroupName
     */
    public void pause(String jobName, String jobGroupName) {
        if (StrUtil.isBlank(jobGroupName)) {
            jobGroupName = DEFAULT_GROUP;
        }
        try {
            JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
            scheduler.pauseJob(jobKey);
        } catch (Exception e) {
            log.error("定时任务暂停失败", e);
            throw new ServiceException("定时任务暂停失败");
        }
    }

    /**
     * 恢复任务
     *
     * @param jobName
     * @param jobGroupName
     */
    public void resume(String jobName, String jobGroupName) {
        if (StrUtil.isBlank(jobGroupName)) {
            jobGroupName = DEFAULT_GROUP;
        }
        try {
            JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
            scheduler.resumeJob(jobKey);
        } catch (Exception e) {
            log.error("恢复定时任务失败", e);
            throw new ServiceException("恢复定时任务失败");
        }
    }

    /**
     * 删除任务
     *
     * @param jobName
     * @param jobGroupName
     */
    public void delete(String jobName, String jobGroupName) {
        if (StrUtil.isBlank(jobGroupName)) {
            jobGroupName = DEFAULT_GROUP;
        }
        try {
            //获取任务触发器
            TriggerKey triggerKey = TriggerKey.triggerKey(jobName);
            //停止触发器
            scheduler.pauseTrigger(triggerKey);
            //移除触发器
            scheduler.unscheduleJob(triggerKey);
            //删除任务
            scheduler.deleteJob(JobKey.jobKey(jobName, jobGroupName));
        } catch (Exception e) {
            log.error("删除定时任务失败", e);
            throw new ServiceException("删除定时任务失败");
        }
    }

    /**
     * 立即执行一次任务
     *
     * @param jobName
     * @param jobGroupName
     */
    public void trigger(String jobName, String jobGroupName) {
        if (StrUtil.isBlank(jobGroupName)) {
            jobGroupName = DEFAULT_GROUP;
        }
        try {
            //根据jobName,jobGroup获取jobKey 立即执行任务
            scheduler.triggerJob(JobKey.jobKey(jobName, jobGroupName));
        } catch (SchedulerException e) {
            log.error("启动一次时任务失败", e);
            throw new ServiceException("执行定时任务失败");
        }
    }

    public static Job getClass(String classname) throws Exception {
        Class<?> class1 = Class.forName(classname);
        return (Job) class1.newInstance();
    }
}
